package ${projectDomain}.adapter.system;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import ${projectDomain}.adapter.BaseAdapter;
import ${projectDomain}.mapper.system.dictionary.SystemDictionaryExtendMapper;
import ${projectDomain}.mapper.system.dictionary.SystemDictionaryMapper;
import ${projectDomain}.pojo.dao.system.dictionary.SystemDictionaryDataDo;
import ${projectDomain}.pojo.dao.system.dictionary.SystemDictionaryDeleteDo;
import ${projectDomain}.pojo.dao.system.dictionary.SystemDictionarySearchDo;
import ${projectDomain}.pojo.dao.system.dictionary.SystemDictionarySingleDo;
import ${projectDomain}.pojo.dao.system.dictionary.type.SystemDictionaryTypeDataDo;
import ${projectDomain}.pojo.vo.system.dictionary.SystemDictionaryTreeVo;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;
import com.unswift.utils.StringUtils;

@Component
@Api(value="数据字典公共服务-此bean可以被任何Service引用", author="liyunlong", date="2024-02-06", version="1.0.0")
public class SystemDictionaryAdapter extends BaseAdapter{
	
	@Autowired
	@ApiField("数据字典数据库操作对象")
	private SystemDictionaryMapper systemDictionaryMapper;
	
	@Autowired
	@ApiField("数据字典数据库扩展操作对象")
	private SystemDictionaryExtendMapper systemDictionaryExtendMapper;
	
	@ApiMethod(value="获取数据字典数据库操作对象", returns=@ApiField("数据库操作对象"))
	public SystemDictionaryMapper getMapper(){
		return systemDictionaryMapper;
	}
	
	@ApiMethod(value="获取数据字典模块名称", returns=@ApiField("模块名称"))
	public String getModule(){
		return "systemDictionary";
	}
	
	@ApiMethod(value="根据主键查询单个对象", params=@ApiField("主键"), returns=@ApiField("主键匹配的对象"))
	public SystemDictionaryDataDo findById(Long id){
		return this.findSingle(new SystemDictionarySingleDo(id, null));
	}
	
	@ApiMethod(value="根据主键列表查询列表对象", params=@ApiField("主键列表"), returns=@ApiField("主键列表匹配的列表对象"))
	public List<SystemDictionaryDataDo> findByIds(List<Long> idList){
		return this.findList(new SystemDictionarySearchDo(idList));
	}
	
	@ApiMethod(value="根据查询对象查询首个对象", params={@ApiField("查询对象"), @ApiField("查询到多个是否抛出异常，可以传入指定提示语，如果提示语为空，则不提示，总的提示与格式：根据%s查询到多条数据，只需要传递%s部分即可")}, returns=@ApiField("首个对象"))
	public SystemDictionaryDataDo findFirst(SystemDictionarySearchDo search, String multipleException){
		List<SystemDictionaryDataDo> list=this.findList(search);
		if(ObjectUtils.isEmpty(list)){
			return null;
		}
		if(ObjectUtils.isNotEmpty(multipleException)){
			ExceptionUtils.trueException(list.size()>1, "multiple.data.found", multipleException);
		}
		return list.get(0);
	}
	
	@ApiMethod(value="查找父资源，如果当前列表不包含完整路径的资源，则会补齐", params = {@ApiField("资源列表"), @ApiField("资源列表的主键集合")})
    public void findParent(List<SystemDictionaryDataDo> list, Set<Long> havingIdSet) {
    	if(ObjectUtils.isNotEmpty(list)) {
    		List<SystemDictionaryDataDo> otherList=new ArrayList<SystemDictionaryDataDo>();
    		Set<Long> otherIdSet=new HashSet<Long>();
    		String parentPath;
    		String[] parentPathArray;
    		long parentId;
    		for (SystemDictionaryDataDo dictionary : list) {
				if(ObjectUtils.isEmpty(dictionary.getParentId())) {
					continue;
				}
				parentPath=dictionary.getParentPath();
				parentPath=parentPath.substring(1, parentPath.length()-1);
				parentPathArray=parentPath.split("\\.");
				for (String item : parentPathArray) {
					parentId=Long.parseLong(item);
					if(!havingIdSet.contains(parentId) && !otherIdSet.contains(parentId)) {
						otherList.add(this.findById(parentId));
						otherIdSet.add(parentId);
					}
				}
			}
    		if(ObjectUtils.isNotEmpty(otherList)) {
    			list.addAll(otherList);
    		}
    	}
    }
    
    @ApiMethod(value="将资源列表解析为树结构", params = {@ApiField("资源列表"), @ApiField("父资源树"), @ApiField("展开路径")})
    public void parseDictionaryToTree(List<SystemDictionaryDataDo> list, SystemDictionaryTreeVo parent, String spreadPath, SystemDictionaryTypeDataDo type) {
    	List<SystemDictionaryTreeVo> childList=new ArrayList<SystemDictionaryTreeVo>();
    	SystemDictionaryTreeVo treeNode;
    	for (SystemDictionaryDataDo dictionary : list) {
			if(ObjectUtils.isEmpty(dictionary.getParentId())) {
				continue;
			}
    		if(dictionary.getParentId().equals(parent.getId())) {
    			treeNode=new SystemDictionaryTreeVo(dictionary.getId(), String.format("%s（%s）", dictionary.getValue(), cacheAdapter.findLanguageByShortName(dictionary.getLanguage())), type.getCode(), type.getName());
    			if(ObjectUtils.isNotEmpty(spreadPath) && StringUtils.contains(spreadPath, dictionary.getId()+"", "\\.")){
    				treeNode.setSpread(true);
    			}
    			childList.add(treeNode);
    			parseDictionaryToTree(list, treeNode, spreadPath, type);
    		}
		}
    	if(ObjectUtils.isNotEmpty(childList)) {
    		parent.setChildren(childList);
    	}
    }
    
    @ApiMethod(value="键是否已存在", params = {@ApiField("类型"),@ApiField("语言"),@ApiField("键")}, returns = @ApiField("是否存在，true：已存在，false：不存在"))
    public boolean existsByKey(String type, String language, String key) {
    	SystemDictionarySearchDo search=new SystemDictionarySearchDo();
    	search.setType(type);
    	search.setLanguage(language);
    	search.setKey(key);
    	return this.findCount(search)>0;
    }
    
    @ApiMethod(value="指定类型、指定语言、指定父项中的值是否已存在", params = {@ApiField("类型"),@ApiField("语言"), @ApiField("父项id"), @ApiField("值"), @ApiField("排除的数据字典id")}, returns = @ApiField("是否存在，true：已存在，false：不存在"))
    public boolean existsByValue(String type, String language, Long parentId, String value, Long excludeId) {
    	SystemDictionarySearchDo search=new SystemDictionarySearchDo();
    	search.setType(type);
    	search.setValue(value);
    	if(ObjectUtils.isEmpty(parentId)) {
    		this.addWhereNull(search, "parent_id_", true);
    	}else {
    		search.setParentId(parentId);
    	}
    	this.addWhereNotEquals(search, "t.id_", excludeId, null);
    	return this.findCount(search)>0;
    }
    
    @ApiMethod(value="指定类型、指定语言、指定父项中的键路径是否已存在", params = {@ApiField("类型"), @ApiField("语言"), @ApiField("键路径"), @ApiField("值")}, returns = @ApiField("是否存在，true：已存在，false：不存在"))
    public boolean existsByKeyPath(String type, String language, String keyPath, Boolean excelExistsPath) {
    	if(excelExistsPath) {
    		return true;
    	}
    	SystemDictionaryDataDo dictionary=findByKeyPath(type, language, keyPath);
    	return ObjectUtils.isNotEmpty(dictionary);
    }
    
    @ApiMethod(value="根据指定类型、指定语言、指定键路径查询对象(有缓存)", params = {@ApiField("类型"), @ApiField("语言"), @ApiField("键路径")}, returns = @ApiField("符合条件的数据字典对象"))
    public SystemDictionaryDataDo findByKeyPath(String type, String language, String keyPath) {
    	if(ObjectUtils.isEmpty(keyPath)) {
    		return null;
    	}
    	Map<String, SystemDictionaryDataDo> typeMap=validateAdapter.getAttribute("dictionaryMap");
		if(ObjectUtils.isNull(typeMap)) {
			typeMap=new HashMap<String, SystemDictionaryDataDo>();
			validateAdapter.setAttribute("dictionaryMap", typeMap);
		}
		String cacheKey=String.format("%s-%s-%s", type, language, keyPath);
		if(typeMap.containsKey(cacheKey)) {//走缓存
			return typeMap.get(cacheKey);
		}else {//走数据库查询
			String key;
	    	String[] keyArray=keyPath.split("/");
	    	SystemDictionarySearchDo search=new SystemDictionarySearchDo();
	    	search.setType(type);
			search.setLanguage(language);
			SystemDictionaryDataDo dictionary=null;
	    	for (int i = 0, length=keyArray.length; i < length; i++) {
	    		key=keyArray[i].trim();
	    		if(i==0) {
	    			search.setKey(key);
	    			dictionary=this.findFirst(search, String.format("%s（%s）", "数据字典", key));
	    		}else {
	    			if(ObjectUtils.isEmpty(dictionary)) {
						break;
					}
	    			search.setKey(key);
					search.setParentId(dictionary.getId());
					dictionary=this.findFirst(search, String.format("%s（%s）", "数据字典", key));
	    		}
	    	}
	    	typeMap.put(cacheKey, dictionary);
	    	return dictionary;
		}
    }
    
    @ApiMethod(value="指定类型、指定父路径中的值是否已存在", params = {@ApiField("类型"), @ApiField("语言"), @ApiField("父key路径"), @ApiField("值"), @ApiField("在excel中是否存在")}, returns = @ApiField("是否存在，true：已存在，false：不存在"))
    public boolean existsByValueToImport(String type, String language, String parentKeyPath, String value) {
    	SystemDictionaryDataDo dictionary=findByKeyPath(type, language, parentKeyPath);
    	SystemDictionarySearchDo search=new SystemDictionarySearchDo();
    	search.setType(type);
		search.setLanguage(language);
		if(ObjectUtils.isEmpty(dictionary)) {
			this.addWhereNull(search, "t.parent_id_", true);//t.parent_id_ is null
		}else {
			search.setParentId(dictionary.getId());
		}
		search.setValue(value);
    	return this.findCount(search)>0;
    }
    
    @ApiMethod(value="获取最大排序值（数据库最大值+1）", params = {@ApiField("数据字典类型"), @ApiField("父部门")}, returns = @ApiField("最大排序值"))
    public int findMaxSort(String type, Long parentId) {
    	SystemDictionarySearchDo search=new SystemDictionarySearchDo();
    	search.setType(type);
    	search.setParentId(parentId);
		return this.findCount(search)+1;
    }
    
    
    public int deleteByType(String type) {
    	SystemDictionaryDeleteDo delete=new SystemDictionaryDeleteDo();
    	this.addWhereEquals(delete, "type_", type, null);
    	return this.delete(delete);
    }
}
